package cn.edu.zut.qixiang.mock;

import lombok.Getter;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;

/**
 * 风况数据采集表数据生成器
 * 为风况数据采集站生成模拟数据（每隔10分钟采集一次）
 * @author 86178
 */
public class WindDataGenerator {

    // 数据库配置
    private static final String URL = "jdbc:mysql://localhost:3306/qixiang_base?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
    private static final String USER = "root";
    private static final String PASSWORD = "520521fcf..@1234";

    // 数据生成参数
    private static final int BATCH_SIZE = 100;
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    // 风向列表
    private static final String[] WIND_DIRECTIONS = {
            "北", "东北", "东", "东南", "南", "西南", "西", "西北"
    };

    public static void main(String[] args) {
        generateWindData();
    }

    /**
     * 生成风况数据（每隔10分钟采集一次）
     */
    public static void generateWindData() {
        String selectStationsSql = "SELECT station_id FROM collection_stations WHERE station_type = '风况数据采集站' ORDER BY station_id";
        String insertDataSql = "INSERT INTO wind_data (collection_station_id, wind_direction, wind_speed, collection_time) VALUES (?, ?, ?, ?)";

        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             PreparedStatement selectStmt = conn.prepareStatement(selectStationsSql);
             PreparedStatement insertStmt = conn.prepareStatement(insertDataSql)) {

            conn.setAutoCommit(false);
            Random random = new Random();

            // 获取所有风况数据采集站
            ResultSet stationRs = selectStmt.executeQuery();

            int batchCount = 0;
            int totalRecords = 0;
            int stationCount = 0;

            // 生成2025年5月1日到9月1日的数据，每10分钟一次
            LocalDateTime startTime = LocalDateTime.of(2025, 5, 1, 0, 0, 0);
            LocalDateTime endTime = LocalDateTime.of(2025, 9, 1, 23, 50, 0);

            System.out.println("开始生成风况数据...");
            System.out.println("时间范围: " + startTime.format(DATE_FORMATTER) + " 到 " + endTime.format(DATE_FORMATTER));
            System.out.println("采集频率: 每10分钟一次");

            // 遍历每个风况采集站
            while (stationRs.next()) {
                int stationId = stationRs.getInt("station_id");
                stationCount++;
                System.out.println("为采集站 " + stationId + " 生成数据...");

                LocalDateTime currentTime = startTime;

                // 为每个时间点生成数据（每10分钟一次）
                while (!currentTime.isAfter(endTime)) {
                    // 生成风况数据
                    WindData windData = generateWindDataForTime(currentTime, random, stationId);

                    // 设置插入参数
                    insertStmt.setInt(1, stationId);
                    insertStmt.setString(2, windData.getWindDirection());
                    insertStmt.setDouble(3, windData.getWindSpeed());
                    insertStmt.setString(4, currentTime.format(DATE_FORMATTER));

                    insertStmt.addBatch();
                    batchCount++;
                    totalRecords++;

                    // 批量提交
                    if (batchCount % BATCH_SIZE == 0) {
                        insertStmt.executeBatch();
                        conn.commit();
                        System.out.println("已提交 " + batchCount + " 条记录，总计 " + totalRecords + " 条");
                    }

                    // 时间增加10分钟
                    currentTime = currentTime.plusMinutes(10);
                }
            }

            // 提交剩余数据
            if (batchCount % BATCH_SIZE != 0) {
                insertStmt.executeBatch();
                conn.commit();
            }

            System.out.println("风况数据生成完成！");
            System.out.println("共为 " + stationCount + " 个采集站生成 " + totalRecords + " 条记录");

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 为指定时间生成风况数据
     */
    private static WindData generateWindDataForTime(LocalDateTime time, Random random, int stationId) {
        WindData data = new WindData();
        int hour = time.getHour();
        int month = time.getMonthValue();
        int minute = time.getMinute();

        // 生成风向（考虑季节主导风向和日变化）
        data.setWindDirection(generateWindDirection(time, random, stationId));

        // 生成风速（考虑日变化、季节变化和天气系统）
        data.setWindSpeed(generateWindSpeed(time, random, data.getWindDirection()));

        return data;
    }

    /**
     * 生成风向（郑州地区主导风向为东北风）
     */
    private static String generateWindDirection(LocalDateTime time, Random random, int stationId) {
        int hour = time.getHour();
        int month = time.getMonthValue();

        // 郑州地区夏季主导风向为东南风，其他季节为东北风
        String dominantDirection;
        if (month >= 6 && month <= 8) {
            dominantDirection = "东南"; // 夏季主导风向
        } else {
            dominantDirection = "东北"; // 其他季节主导风向
        }

        // 日变化：白天受热力环流影响，风向可能变化
        double diurnalEffect = 0.0;
        if (hour >= 9 && hour <= 17) {
            // 白天可能产生局地环流
            diurnalEffect = random.nextDouble() * 0.3;
        }

        // 根据主导风向生成实际风向
        if (random.nextDouble() < 0.6 - diurnalEffect) {
            // 60%的概率出现主导风向
            return dominantDirection;
        } else if (random.nextDouble() < 0.8) {
            // 20%的概率出现相邻风向
            return getAdjacentDirection(dominantDirection, random);
        } else {
            // 20%的概率出现其他随机风向
            return WIND_DIRECTIONS[random.nextInt(WIND_DIRECTIONS.length)];
        }
    }

    /**
     * 获取相邻风向
     */
    private static String getAdjacentDirection(String direction, Random random) {
        for (int i = 0; i < WIND_DIRECTIONS.length; i++) {
            if (WIND_DIRECTIONS[i].equals(direction)) {
                // 随机选择左侧或右侧相邻风向
                if (random.nextBoolean()) {
                    return WIND_DIRECTIONS[(i + 1) % WIND_DIRECTIONS.length];
                } else {
                    return WIND_DIRECTIONS[(i - 1 + WIND_DIRECTIONS.length) % WIND_DIRECTIONS.length];
                }
            }
        }
        return direction;
    }

    /**
     * 生成风速（m/s）
     */
    private static double generateWindSpeed(LocalDateTime time, Random random, String windDirection) {
        int hour = time.getHour();
        int month = time.getMonthValue();

        // 基准风速（郑州地区平均风速）
        double baseSpeed = getBaseWindSpeed(month);

        // 日变化（午后风速较大，夜间风速较小）
        double diurnalVariation = calculateDiurnalVariation(hour);

        // 风向对风速的影响（某些风向通常风速较大）
        double directionEffect = calculateDirectionEffect(windDirection);

        // 天气系统影响
        double weatherEffect = calculateWeatherEffect(time, random);

        // 随机波动
        double randomFluctuation = (random.nextDouble() - 0.5) * 1.5;

        // 计算最终风速
        double windSpeed = baseSpeed + diurnalVariation + directionEffect + weatherEffect + randomFluctuation;

        // 确保风速不为负，并限制最大风速
        windSpeed = Math.max(0.1, Math.min(windSpeed, 15.0));

        return Math.round(windSpeed * 10) / 10.0;
    }

    /**
     * 获取基准风速（郑州地区各月平均）
     */
    private static double getBaseWindSpeed(int month) {
        switch (month) {
            case 5: // 5月：春季，风速较大
                return 3.2;
            case 6: // 6月：初夏，风速适中
                return 2.8;
            case 7: // 7月：盛夏，风速较小
                return 2.3;
            case 8: // 8月：盛夏，风速较小
                return 2.4;
            case 9: // 9月：初秋，风速增大
                return 2.9;
            default:
                return 2.5;
        }
    }

    /**
     * 计算风速的日变化（午后风速大，夜间风速小）
     */
    private static double calculateDiurnalVariation(int hour) {
        // 午后（13-16时）风速最大，夜间（1-4时）风速最小
        if (hour >= 13 && hour <= 16) {
            return 1.5; // 午后增强
        } else if (hour >= 1 && hour <= 4) {
            return -1.0; // 夜间减弱
        } else if (hour >= 9 && hour <= 11) {
            return 0.8; // 上午逐渐增强
        } else if (hour >= 17 && hour <= 19) {
            return 0.5; // 傍晚仍较强
        } else {
            return 0.0;
        }
    }

    /**
     * 计算风向对风速的影响
     */
    private static double calculateDirectionEffect(String windDirection) {
        // 北风、西北风通常风速较大
        switch (windDirection) {
            case "北":
            case "西北":
                return 0.8;
            case "东北":
            case "西":
                return 0.4;
            case "东南":
            case "南":
                return -0.2; // 南风通常较柔和
            default:
                return 0.0;
        }
    }

    /**
     * 计算天气系统对风速的影响
     */
    private static double calculateWeatherEffect(LocalDateTime time, Random random) {
        // 使用日期作为种子，使同一日期的天气一致
        long daySeed = time.toLocalDate().toEpochDay();
        Random dayRandom = new Random(daySeed);

        // 模拟天气系统：0-平静, 1-一般, 2-有风, 3-大风
        int weatherSystem = dayRandom.nextInt(4);

        switch (weatherSystem) {
            case 0: // 平静天气
                return -1.0;
            case 1: // 一般天气
                return 0.0;
            case 2: // 有风天气
                return 2.0;
            case 3: // 大风天气
                return 4.0 + dayRandom.nextDouble() * 3.0;
            default:
                return 0.0;
        }
    }

    /**
     * 风况数据实体类
     */
    @Getter
    static class WindData {
        private String windDirection;
        private double windSpeed;

        public void setWindDirection(String windDirection) { this.windDirection = windDirection; }

        public void setWindSpeed(double windSpeed) { this.windSpeed = windSpeed; }
    }
}